package ru.susu.algebra.partition;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author akargapolov
 * @since: 18.03.2009
 */
public class OrderBasedPartition extends PartitionBase
{
	private static final long serialVersionUID = 8223794390962630030L;

	private Integer _order;
	private Integer _n;

	protected OrderBasedPartition(int order, int n)
	{
		_order = Integer.valueOf(order);
		_n = Integer.valueOf(n);
	}

	protected OrderBasedPartition(Integer[] array)
	{
		_n = 0;
		for (Integer number : array)
			_n += number;
		Arrays.sort(array);
		_order = PartitionEnumerator.getNumber(array).intValue();
	}

	@Override
	public Integer[] getArrayRepresentation()
	{
		return PartitionEnumerator.getArray(_order, _n);
	}

	@Override
	public Partition clone()
	{
		return new OrderBasedPartition(_order, _n);
	}

	@Override
	public boolean add(Integer number, Integer count)
	{
		Integer[] array = new Integer[count];
		Arrays.fill(array, number);

		List<Integer> list = new ArrayList<Integer>();
		Collections.addAll(list, getArrayRepresentation());
		Collections.addAll(list, array);
		Collections.sort(list);

		_order = PartitionEnumerator.getNumber(list.toArray(new Integer[list.size()])).intValue();
		_n += number * count;

		return true;
	}

	@Override
	public Integer getLength()
	{
		return getArrayRepresentation().length;
	}

	@Override
	public Integer getOrderNumber()
	{
		return _order;
	}

	@Override
	public Integer getPresentedNumber()
	{
		return _n;
	}

	@Override
	public boolean remove(Integer number, Integer count)
	{
		List<Integer> list = new ArrayList<Integer>();
		Collections.addAll(list, getArrayRepresentation());

		if (!list.contains(number))
			return false;

		int count1 = count;

		while (count1 > 0 && list.contains(number))
		{
			count1--;
			list.remove(number);
		}

		_order = PartitionEnumerator.getNumber(list.toArray(new Integer[list.size()])).intValue();
		_n -= number * (count - count1);

		return true;
	}

	@Override
	public int hashCode()
	{
		return _order;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (this.getClass() != obj.getClass())
			return false;
		OrderBasedPartition other = (OrderBasedPartition) obj;
		if (_n == null)
		{
			if (other._n != null)
				return false;
		}
		else if (!_n.equals(other._n))
			return false;
		if (_order == null)
		{
			if (other._order != null)
				return false;
		}
		else if (!_order.equals(other._order))
			return false;
		return true;
	}

}
